<!-- JsonTreeNode.vue -->
<template>
	<div class="tree-node">
		<div class="node-header" :class="{ expandable: isExpandable }" @click="toggleExpand">
			<!-- 展开/折叠指示器 -->
			<span v-if="isExpandable" class="toggle" :class="{ expanded: isExpanded }">
				{{ isExpanded ? '−' : '+' }}
			</span>

			<!-- 单选控件 - 只在非一级节点显示 -->
			<a-radio v-if="!isRootLevel" :name="`${radioGroupName}`" :checked="isSelected" @click.stop="handleSelect" />

			<!-- 键名显示 -->
			<span class="key">{{ nodeKey }}: </span>

			<!-- 值显示 -->
			<span class="value" :class="valueTypeClass">
				{{ displayValue }}
			</span>
		</div>

		<!-- 子节点容器 -->
		<div v-if="isExpanded" class="children-container">
			<template v-for="(childValue, childKey) in childrenData" :key="childKey">
				<json-tree-node
					:node-data="{ [childKey]: childValue }"
					:parent-path="currentPath"
					:selected-path="selectedPath"
					:radio-group-name="radioGroupName"
					@node-selected="$emit('node-selected', $event)"
				/>
			</template>
		</div>
	</div>
</template>

<script setup>
	import { computed, ref, toRefs } from 'vue'
	// import { v4 as uuidv4 } from 'uuid'

	const props = defineProps({
		nodeData: {
			type: Object,
			required: true
		},
		parentPath: {
			type: String,
			default: ''
		},
		selectedPath: {
			type: String,
			default: ''
		},
		radioGroupName: {
			type: [String, Number],
			// default: uuidv4() // 生成唯一ID避免多实例冲突
			default: new Date().getTime() // 生成唯一ID避免多实例冲突
		}
	})

	const emit = defineEmits(['node-selected'])

	// 状态管理
	// 判断是否为一级节点
	const isRootLevel = computed(() => !props.parentPath)

	// 状态管理 - 一级节点默认展开
	const isExpanded = ref(isRootLevel.value)
	// const [nodeKey, nodeValue] = Object.entries(props.nodeData)[0]
	// const nodeKey = Object.entries(props.nodeData)[0][0]
	// const nodeValue = Object.entries(props.nodeData)[0][1]

	// 当前节点路径计算
	const nodeKey = computed(() => {
		return Object.entries(props.nodeData)[0][0]
	})
	const nodeValue = computed(() => {
		return Object.entries(props.nodeData)[0][1]
	})

	// 当前节点路径计算
	const currentPath = computed(() => {
		if (!props.parentPath) return nodeKey.value
		// 处理数组索引路径
		if (/^\d+$/.test(nodeKey.value)) {
			return `${props.parentPath}[${nodeKey.value}]`
		}
		return `${props.parentPath}.${nodeKey.value}`
	})

	// 类型判断
	const isExpandable = computed(() => {
		return typeof nodeValue.value === 'object' && nodeValue.value !== null
	})

	const valueTypeClass = computed(() => {
		if (nodeValue.value === null) return 'null'
		if (Array.isArray(nodeValue.value)) return 'array'
		return typeof nodeValue.value
	})

	// 显示值格式化
	const displayValue = computed(() => {
		if (nodeValue.value === null) return 'null'
		if (Array.isArray(nodeValue.value)) return `[ ${nodeValue.value.length} items ]`
		if (typeof nodeValue.value === 'object') return '{ ... }'
		if (typeof nodeValue.value === 'string') return `"${nodeValue.value}"`
		return nodeValue.value.toString()
	})

	// 子节点数据处理
	const childrenData = computed(() => {
		if (Array.isArray(nodeValue.value)) {
			return Object.fromEntries(nodeValue.value.map((item, index) => [index, item]))
		}
		return nodeValue.value
	})

	// 选中状态判断
	const isSelected = computed(() => {
		// 处理完整路径的比较
		if (!props.selectedPath) return false
		return props.selectedPath === currentPath.value
	})

	// 事件处理
	const toggleExpand = () => {
		if (isExpandable.value) {
			isExpanded.value = !isExpanded.value
		}
	}

	const handleSelect = () => {
		emit('node-selected', {
			path: currentPath.value,
			value: nodeValue.value
		})
	}
</script>

<style scoped>
	.tree-node {
		margin-left: var(--tree-indent);
		transition: all 0.3s ease;
	}

	.node-header {
		display: flex;
		align-items: center;
		padding: 6px;
		margin: 2px 0;
		border-radius: 2px;
		cursor: default;
		transition: background 0.2s;
	}

	.node-header:hover {
		background: #f5f5f5;
	}

	.node-header.expandable {
		cursor: pointer;
	}

	.toggle {
		display: inline-block;
		width: 18px;
		text-align: center;
		margin-right: 6px;
		color: var(--primary-color);
		font-weight: bold;
		user-select: none;
	}

	input[type='radio'] {
		margin: 0 8px 0 4px;
		accent-color: var(--primary-color);
	}

	.key {
		color: #881391;
		margin-right: 8px;
		font-weight: 500;
	}

	.value {
		color: var(--text-color);
		opacity: 0.8;
	}

	.value.null {
		color: #999;
		font-style: italic;
	}

	.value.array {
		color: #4caf50;
	}

	.value.string {
		color: #c41a16;
	}

	.value.number {
		color: #1c00cf;
	}

	.value.boolean {
		color: #0d22aa;
	}

	.children-container {
		margin-left: 12px;
		border-left: 1px solid #eee;
		padding-left: 8px;
		animation: fadeIn 0.3s;
	}

	@keyframes fadeIn {
		from {
			opacity: 0;
		}
		to {
			opacity: 1;
		}
	}
</style>
